package com.ssm.security.my;

/**
 * Created by wchen on 2017/7/14.
 */
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

import com.ssm.security.JWT.TokenAuthenticationService;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.context.HttpRequestResponseHolder;
import org.springframework.security.web.context.NullSecurityContextRepository;
import org.springframework.security.web.context.SecurityContextRepository;
import org.springframework.util.Assert;
import org.springframework.web.filter.GenericFilterBean;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 *这个filter有两个主要的任务，第一，它负责在HTTP请求之中保存SecurityContext内容，
 * 并且当请求完毕之后清理SecurityContextHolder；第二，最重要的功能是，清理ThreadLocal局部变量，
 * 因为一个线程可能会被代替并被放入线程池中，这样一些用户可以访问到security的内容，
 * 这个线程可能会在持有坏的凭证的时候可以继续执行一些操作。
 * 在关闭session后要让后面的授权filter能能够获得到用户的权限信息，就不能在这里删除SecurityContexHolder.
 * 即SecurityContextHolder.clearContext();
 * 参考博文：http://blog.csdn.net/yecong111/article/details/16969835
 */

public class MySecurityContextPersistenceFilter extends GenericFilterBean {
    static final String FILTER_APPLIED = "__spring_security_scpf_applied";
    private SecurityContextRepository repo;
    private boolean forceEagerSessionCreation;
    private String loginUrl;

    public String getLoginUrl() {
        return loginUrl;
    }

    public void setLoginUrl(String loginUrl) {
        this.loginUrl = loginUrl;
    }

    public MySecurityContextPersistenceFilter() {
        this(new NullSecurityContextRepository());
    }

    public MySecurityContextPersistenceFilter(NullSecurityContextRepository repo) {
        this.forceEagerSessionCreation = false;
        this.repo = repo;
    }

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException{
        HttpServletRequest request = (HttpServletRequest)req;
        HttpServletResponse response = (HttpServletResponse)res;
        if(request.getAttribute("__spring_security_scpf_applied") != null) {
            chain.doFilter(request, response);
        } else {
            boolean debug = this.logger.isDebugEnabled();
            request.setAttribute("__spring_security_scpf_applied", Boolean.TRUE);//执行这个判断是因为这个当前这个java类是插入到过滤器类前面(before)原始的过滤器并没有失效，有了这个set后，执行到原始的filter同样位置就不会再进行一次过滤内容了
/*            if(this.forceEagerSessionCreation) {
                HttpSession holder = request.getSession();
                if(debug && holder.isNew()) {
                    this.logger.debug("Eagerly created session: " + holder.getId());
                }
            }*/

            HttpRequestResponseHolder holder1 = new HttpRequestResponseHolder(request, response); //将request、response对象交给HttpRequestResponseHolder维持
            /*SecurityContext contextBeforeChainExecution = this.repo.loadContext(holder1);*///当关闭了session，返回的是null authentication
            try {
                String URL = holder1.getRequest().getRequestURL().toString();
                if (!URL.equals(loginUrl)){
                /*从request中提取出token信息，并获取权限信息，如果是登陆，这里则为null*/
                    Authentication authentication = null;
                    try {
                        authentication = TokenAuthenticationService.getAuthentication(holder1.getRequest(), holder1.getResponse());
                    } catch (IOException e) {
                        //response.setHeader("Authentication",JSONResult.fillResultString(600, e.getMessage(), null, null));
                    }
                /*将权限信息存入SecurityContextHolder，用来后面授权使用，如果是登陆，则授权信息也是空*/
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }

                chain.doFilter(holder1.getRequest(), holder1.getResponse());//执行登陆验证或者授权认证
            } finally {
                /*if(var13) {
                    SecurityContext contextAfterChainExecution1 = SecurityContextHolder.getContext();
                    SecurityContextHolder.clearContext();
                    this.repo.saveContext(contextAfterChainExecution1, holder1.getRequest(), holder1.getResponse());
                    request.removeAttribute("__spring_security_scpf_applied");
                    if(debug) {
                        this.logger.debug("SecurityContextHolder now cleared, as request processing completed");
                    }

                }*/
            }

            /*SecurityContext contextAfterChainExecution = SecurityContextHolder.getContext();*/
            SecurityContextHolder.clearContext();
            /*this.repo.saveContext(contextAfterChainExecution, holder1.getRequest(), holder1.getResponse());*/ //将SecurityContext实例持久化到session中
            request.removeAttribute("__spring_security_scpf_applied");
            if(debug) {
                this.logger.debug("SecurityContextHolder now cleared, as request processing completed");

            }
        }
    }

    /** @deprecated */
    @Deprecated
    public void setSecurityContextRepository(SecurityContextRepository repo) {
        Assert.notNull(repo, "SecurityContextRepository cannot be null");
        this.repo = repo;
    }

    public void setForceEagerSessionCreation(boolean forceEagerSessionCreation) {
        this.forceEagerSessionCreation = forceEagerSessionCreation;
    }
}



